﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Kimd.Common;
using Kimd.Logic.Model;

namespace Kimd.Logic
{
    public class FlowManager : SingletonProvider<FlowManager>
    {
        private bool _pauseFlag = true;
        public bool IsRunFalg { get; set; }
        public bool PauseFlag
        { 
            get { return _pauseFlag; }
        }
        private bool _breakFlag;
        private Dictionary<string, Dictionary<string, SignalBase>> _flowSignals; 
        public SerializableDictionary<string, FlowBase> Flows { get; set; }
        public Action OnFlowStartPause { get; set; }
        public Action OnFlowPaused { get; set; }
        public bool AllFlowPaused
        {
            get 
            {
                bool p = true;
                foreach (var item in Flows)
                {
                    if (!item.Value.Status.IsPaused && item.Value.Status.IsEnabled)
                    {
                        p = false;
                        break;
                    }
                }
                return p; 
            }
        }
        public bool AllFlowHomeFinished
        {
            get
            {
                bool p = true;
                foreach (var item in Flows)
                {
                    if (!item.Value.Status.IsHomeFinish && item.Value.Status.IsEnabled)
                    {
                        p = false;
                        break;
                    }
                }
                return p;
            }
        }
        public bool AllFlowStopped
        {
            get
            {
                bool p = true;
                foreach (var item in Flows)
                {
                    if (!item.Value.Status.IsStopped && item.Value.Status.IsEnabled && !item.Value.Status.IsBackground)
                    {
                        p = false;
                        break;
                    }
                }
                return p;
            }
        }
        public List<FlowStatus> AllFlowStatus { get; set; }
        public FlowManager()
        {
            this.Flows = new SerializableDictionary<string, FlowBase>();
            this._flowSignals = new Dictionary<string, Dictionary<string, SignalBase>>();
            this.AllFlowStatus = new List<FlowStatus>();
        }
        /// <summary>
        /// 打开所有流程，开始线程运行
        /// </summary>
        public void Open()
        {
            foreach (var flow in Flows.Values)
            {
                flow.Open();
            }
        }
        /// <summary>
        /// 第一次启动或每次停止后 执行，需初始化所有的线程，复位各个信号
        /// </summary>
        public void Init(out string errInfo)
        {
            errInfo = "";
            _breakFlag = false;
            //复位所有线程间通信信号
            ResetAllSignal();
            foreach (FlowBase flow in Flows.Values)
            {
                flow.Init(out errInfo);
                if (!string.IsNullOrEmpty(errInfo))
                    return;
            }
        }
        public void Reset()
        {
            _breakFlag = false;
        }
        public void Start()
        {
            this._pauseFlag = false;
        }
        public void Pause()
        {
            this._pauseFlag = true;
            if(OnFlowStartPause != null)
                OnFlowStartPause();
            IsRunFalg = false;
        }
        /// <summary>
        /// 停止所有正在执行中的线程，从头开始运行
        /// </summary>
        public void Stop()
        {
            //暂停信号给出
            _pauseFlag = true;
            //跳出所有正在等待的信号
            foreach (Dictionary<string, SignalBase> allSignals in _flowSignals.Values)
            {
                foreach (SignalBase signal in allSignals.Values)
                {
                    signal.Break();
                }
            }
            //跳出所有可能的循环
            _breakFlag = true;
            IsRunFalg = false;
        }
        /// <summary>
        /// 关闭所有流程，停止线程运行
        /// </summary>
        public void Close()
        {
            foreach (var flow in Flows.Values)
            {
                flow.Close();
            }
        }
        public bool IsBreak()
        {
            return _breakFlag;
        }
        public void WaitForStart()
        {
            //暂停信号有且 break信号无时，等待
            while(_pauseFlag && !_breakFlag)
            {
                System.Threading.Thread.Sleep(20);
            }
        }
        public bool WaitForSignal(string fromFlowName, string signalName)
        {
            return this._flowSignals[fromFlowName][signalName].Wait();
        }
        public void RegisterSignal(string flowName, string signalName, bool initState = false)
        {
            DirectSignal signal = new DirectSignal(initState);
            if (!this._flowSignals.ContainsKey(flowName))
                this._flowSignals.Add(flowName, new Dictionary<string, SignalBase>());
            this._flowSignals[flowName].Add(signalName, signal);
        }
        public void RegisterSwitchSignal(string flowName, string signalName, bool initState = false)
        {
            SwitchSignal signal = new SwitchSignal(initState);
            if (!this._flowSignals.ContainsKey(flowName))
                this._flowSignals.Add(flowName, new Dictionary<string, SignalBase>());
            this._flowSignals[flowName].Add(signalName, signal);
        }
        public SignalBase GetSignal(string flowName, string signalName)
        {
            return this._flowSignals[flowName][signalName];
        }
        public void SetSignal(string flowName, string signalName)
        {
            this._flowSignals[flowName][signalName].Set();
        }
        public void ResetSignal(string flowName, string signalName)
        {
            this._flowSignals[flowName][signalName].Reset();
        }
        public void ResetAllSignal()
        {
            if (_flowSignals.Count > 0)
            {
                foreach (var item in _flowSignals.Values)
                {
                    if (item.Count > 0)
                    {
                        foreach (var signal in item)
                        {
                            signal.Value.Reset();
                        }
                    }
                }
            }
        }
        public void ResetAllSignalBreak()
        {
            if (_flowSignals.Count > 0)
            {
                foreach (var item in _flowSignals.Values)
                {
                    if (item.Count > 0)
                    {
                        foreach (var signal in item)
                        {
                            signal.Value.ResetBreak();
                        }
                    }
                }
            }
        }
        public void AddFlow(FlowBase flow)
        {
            this.Flows.Add(flow.Description, flow);
            this.AllFlowStatus.Add(flow.Status);
        }
        public void RemoveFlow(string flowName)
        {
            this.Flows.Remove(flowName);
        }
        public FlowBase SelectFlow(string flowName)
        {
            return Flows[flowName];
        }
    }
}
